<template>
    <div class="map-box" ref="mapbox">
        <div id="map"></div>
        <div class="button-box">
            <el-button type="primary" @click="openDraw">开启自定义绘制</el-button>
            <el-button type="primary" @click="closeDraw">关闭自定义绘制</el-button>
            <el-button v-show="isOpen" @click="addMarker">添加点</el-button>
            <el-button v-show="isOpen" @click="addPolyline">添加线</el-button>
            <el-button v-show="isOpen" @click="addPolygon">添加多边形</el-button>
            <el-button @click="removeAllPoint">清除所有点</el-button>
            <el-button @click="removeAllLine">清除所有线</el-button>
            <el-button @click="removeAllArea">清除所有面</el-button>
            <!-- <el-button @click="removeOverlay">清除当前覆盖物</el-button> -->
            <el-button @click="removeAllOverlay">清除所有覆盖物</el-button>
        </div>
        <div id="custom-menu" ref="customMenu">
            <div class="menu-item" id="menu-item-1">
                <el-button type="primary" @click="overlayEdit">编辑</el-button>
            </div>
            <div class="menu-item" id="menu-item-2">
                <el-button type="primary" @click="overlayRemove">删除</el-button>
            </div>
        </div>
    </div>
</template>

<script>
import { DrawScene, PolylineDraw, PolygonDraw, MarkerDraw, OperateEventType, PolylineEdit, MarkerEdit, PolygonEdit } from 'bmap-draw';
export default {
    prop: {
        config: {
            type: Object,
            default: {}
        }
    },
    data() {
        return {
            isOpen: false,
            mapEntity: null,
            // 当前地图上的覆盖物
            overlays: [],
            // 当前点击选中的覆盖物
            curClickOverLay: null,
            // 场景类
            scene: null,
            polyline: null,
            polygon: null,
            marker: null,
            polylineEdit: null,
            polygonEdit: null,
            markerEdit: null,
        }
    },
    mounted() {
        // 阻止右键菜单
        this.$refs.mapbox.addEventListener("contextmenu", function (evt) {
            evt.preventDefault()
        })
        //点击页面其他地方隐藏菜单
        this.$refs.mapbox.addEventListener('click', (e) => {
            this.hideMenu()
        });
        /**
         * 初始化地图
         */
        this.initMap();
        /**
         * 绘制点
         */
        // 定义插入点的图标
        // let myIcon = new BMapGL.Icon(config.img.url, new BMapGL.Size(config.img.x, config.img.y), {
        //     // 指定定位位置。  
        //     // 当标注显示在地图上时，其所指向的地理位置距离图标左上   
        //     // 角各偏移10像素和25像素。您可以看到在本例中该位置即是  
        //     // 图标中央下端的尖角位置。   
        //     anchor: new BMapGL.Size(10, 25),
        //     // 设置图片偏移。  
        //     // 当您需要从一幅较大的图片中截取某部分作为标注图标时，您  
        //     // 需要指定大图的偏移位置，此做法与css sprites技术类似。   
        //     imageOffset: new BMapGL.Size(0, 0 - 25)   // 设置图片偏移   
        // });
        let pointConfig = {
            // icon: myIcon
        };
        this.drawPoint({ lon: 118.29, lat: 35.122 }, pointConfig);
        /**
         * 绘制线
         */
        let linePath = [
            { lon: 116.399, lat: 39.910 },
            { lon: 116.405, lat: 39.920 },
            { lon: 116.423493, lat: 39.907445 }
        ];
        let lineConfig = {
            strokeStyle: 'dashed', // 线段样式
            strokeColor: 'blue', // 线段颜色
            strokeTexture: {
                url: 'https://mapopen-pub-jsapigl.bj.bcebos.com/svgmodel/Icon_road_blue_arrow.png', // 线段纹理图片
                width: 16, // 图片宽度
                height: 64  // 图片高度
            }, // 线段纹理
            strokeWeight: 8, // 线段宽度
            strokeOpacity: 0.8, // 线段透明度
            enableEditing: true, // 是否可编辑
            // node: node // 线节点
        };
        this.drawLine(linePath, lineConfig);

        /**
         * 绘制区域
         */
        let path = [
            {
                lon: 116.387112,
                lat: 39.920977
            },
            {
                lon: 116.385243,
                lat: 39.913063
            },
            {
                lon: 116.394226,
                lat: 39.917988
            },
            {
                lon: 116.401772,
                lat: 39.921364
            },
            {
                lon: 116.41248,
                lat: 39.927893
            },
        ];
        //线、面、圆编辑节点可配置图标
        // let nodeT = new BMapGL.Icon('//mapopen-pub-jsapigl.bj.bcebos.com/demoimg/ditie_beijing_2.png', new BMapGL.Size(11, 11), {
        //     offset: new BMapGL.Size(5, 5)
        // });
        // let node = new BMapGL.Icon('//mapopen-pub-jsapigl.bj.bcebos.com/demoimg/zhongheyiyuan.png', new BMapGL.Size(11, 11), {
        //     offset: new BMapGL.Size(5, 5)
        // });
        let config = {
            zIndex: 100, // 线段层级
            // node: node, // 线节点
            // nodeT: nodeT, // 线段中间节点
            fillColor: 'pink',// 区域填充颜色
            fillOpacity: 1, // 填充透明度
            strokeStyle: 'dashed', // 线段样式
            strokeColor: 'blue',  // 线段颜色
            strokeWeight: 5, // 线段宽度
            strokeOpacity: 1, // 线段透明度
        }
        this.drawArea(path, config);
        /**
         * 绘制镂空区域
         */
        let holePath = [[
            { lon: 116.35965, lat: 39.92855 },
            { lon: 116.35391, lat: 39.93740 },
            { lon: 116.34873, lat: 39.92855 },
            { lon: 116.34696, lat: 39.91527 },
            { lon: 116.38335, lat: 39.90930 },
            { lon: 116.38121, lat: 39.93461 },
            { lon: 116.37920, lat: 39.92855 },
            { lon: 116.37518, lat: 39.93674 },
            { lon: 116.36885, lat: 39.92877 }
        ], [
            { lon: 116.35, lat: 39.925 },
            { lon: 116.36, lat: 39.925 },
            { lon: 116.36, lat: 39.92 },
            { lon: 116.35, lat: 39.92 },
            { lon: 116.35, lat: 39.925 }
        ], [
            { lon: 116.365, lat: 39.925 },
            { lon: 116.37, lat: 39.925 },
            { lon: 116.37, lat: 39.92 },
            { lon: 116.365, lat: 39.92 },
            { lon: 116.365, lat: 39.925 },
        ]];
        let configHole = {
            zIndex: 5,
            fillOpacity: 1,
            fillColor: 'pink',
            strokeColor: '#8055e3',
            strokeWeight: 5,
            strokeOpacity: 1
        };
        this.drawAreaHole(holePath, configHole);

        /**
         * 批量绑定点击事件 最后调用
         */
        this.bindEvent()
    },
    methods: {
        // 开启自绘制
        openDraw() {
            if (this.mapEntity) {
                this.isOpen = true;
            }
        },
        /**
         * 关闭自绘制
         */
        closeDraw() {
            if (this.mapEntity) {
                this.polygon.closeAll()
                this.polyline.closeAll()
                this.marker.closeAll()
                this.isOpen = false;
            }
        },
        /**
         * 初始化自定义绘制工具
         */
        initSelfDrawTool(config) {
            if (this.mapEntity) {
                // 初始化点绘制类
                const myIcon = new BMapGL.Icon('//bj.bcebos.com/v1/mapopen-pub-jsapigl/assets/images/markericon.png',
                    new BMapGL.Size(37, 47));
                this.marker = new MarkerDraw(this.scene, {
                    isOpen: false, // 是否开启绘制
                    isSeries: false, // 是否开启批量绘制
                    enableDragging: false, // 是否可拖拽
                    baseOpts: {
                        icon: myIcon
                    }
                });
                // 初始化线绘制类
                this.polyline = new PolylineDraw(this.scene, {
                    hideTip: false, // 显示绘制提示（默认显示）
                    isOpen: false, // 是否开启绘制
                    isSeries: false, // 是否开启批量绘制
                    labelOptions: {
                        borderRadius: '2px',
                        background: '#b5d3fb',
                        border: '1px solid #b5d3fb',
                        color: '#333',
                        fontSize: '12px',
                        letterSpacing: '0',
                        padding: '5px'
                    },
                    baseOpts: {
                        strokeWeight: 4,
                        strokeOpacity: 1,
                        fillOpacity: 0.2
                    }
                });
                // 初始化面绘制类
                this.polygon = new PolygonDraw(this.scene, {
                    hideTip: true, // 隐藏绘制提示
                    isSeries: false, // 是否开启批量绘制
                    isOpen: false,// 是否开启绘制
                    labelOptions: {
                        borderRadius: '2px',
                        background: 'pink',
                        border: '1px solid #b5d3fb',
                        color: '#333',
                        fontSize: '12px',
                        letterSpacing: '0',
                        padding: '5px'
                    },
                    baseOpts: {
                        fillColor: 'pink', // 面填充颜色
                        strokeWeight: 5,
                        strokeOpacity: 1,
                        fillOpacity: 0.5
                    }
                });
                this.markerEdit = new MarkerEdit(this.scene);
                this.polylineEdit = new PolylineEdit(this.scene);
                this.polygonEdit = new PolygonEdit(this.scene);
            }
        },
        addMarker() {
            // this.mapEntity.addEventListener('click', (e) => {
            //     console.log(e.latlng.lng, e.latlng.lat);
            //     let marker = this.drawPoint({ lon: e.latlng.lng, lat: e.latlng.lat })
            //     // this.$emit('addMarker', marker); // 事件回调
            // });
            this.marker.open()
        },
        addPolyline() {
            this.polyline.open()
        },
        addPolygon() {
            this.polygon.open()
        },
        overlayEdit() {
            console.log(111, this.curClickOverLay);
            if (this.curClickOverLay instanceof BMapGL.Marker) {
                console.log('编辑', 1111);
                this.markerEdit.open(this.curClickOverLay)
            } else if (this.curClickOverLay instanceof BMapGL.Polyline) {
                console.log('编辑', 1111);
                this.polylineEdit.open(this.curClickOverLay)
            } else if (this.curClickOverLay instanceof BMapGL.Polygon) {
                console.log('编辑', 1111);
                this.polygonEdit.open(this.curClickOverLay)
            }
            this.hideMenu()
        },
        overlayRemove() {
            this.removeOverlay()
            this.hideMenu()
        },
        /**
         * 动图初始化
         * @param config 其他配置
         * @returns {void}
         */
        initMap(config) {
            this.mapEntity = new BMapGL.Map("map")
            // 设置中心
            let point = new BMapGL.Point(116.404, 39.915);
            this.mapEntity.centerAndZoom(point, 15);
            //开启鼠标滚轮缩放
            this.mapEntity.enableScrollWheelZoom(true);
            // 创建场景类 场景类，作为鼠标绘制的管理类，用于管理全局的事件监听、覆盖物存取、获取当前交互对象等。
            this.scene = new DrawScene(this.mapEntity);
            // 绘制完成事件监听
            this.scene.addEventListener(OperateEventType.COMPLETE, e => {
                // 将绘制完成的覆盖物添加到数组中
                this.overlays.push(e.target.overlay)
                this.bindOne(e.target.overlay)
            })
            this.initSelfDrawTool()
        },
        /**
         * 绘制点
         * @param poi {Object} 经纬度
         * @param config 其他配置
         * @returns {void}
         */
        drawPoint(poi, config) {
            let point = new BMapGL.Point(poi.lon, poi.lat);
            // 创建标注
            let marker = new BMapGL.Marker(point, config);
            // 将标注添加到地图中
            this.mapEntity.addOverlay(marker);
            // 将覆盖物添加数组中
            this.overlays.push(marker);
            this.scene.instances.push(marker)
            return marker;
        },
        /**
         * 绘制区域
         * @param path {Array} 线路坐标
         * @param config {Object} 其他配置
         */
        drawArea(path, config) {
            path = path.map((item) => {
                return new BMapGL.Point(item.lon, item.lat);
            });
            let polygon = new BMapGL.Polygon(path, config);
            this.mapEntity.addOverlay(polygon);
            // 将覆盖物添加数组中
            this.overlays.push(polygon);
            this.scene.instances.push(polygon)
        },
        /**
         * 绘制镂空面
         * @param path {Array}二维数组，第一个数组是绘制层，剩下的数组为镂空区域 线路坐标
         * @param config {Object} 其他配置
         */
        drawAreaHole(path, config) {
            for (let i in path) {
                path[i] = path[i].map((item) => {
                    return new BMapGL.Point(item.lon, item.lat);
                });
            }
            let polyHole = new BMapGL.Polygon(path, config);
            this.mapEntity.addOverlay(polyHole);
            // 将覆盖物添加数组中
            this.overlays.push(polyHole);
            this.scene.instances.push(polyHole)
        },
        /**
         * 绘制线
         * @param path {Array} 线路坐标
         * @param config {Object} 其他配置
         */
        drawLine(path, config) {
            path = path.map((item) => {
                return new BMapGL.Point(item.lon, item.lat);
            });
            let polyline = new BMapGL.Polyline(path, config);
            this.mapEntity.addOverlay(polyline);
            // 将覆盖物添加数组中
            this.overlays.push(polyline);
            this.scene.instances.push(polyline)
        },
        /**
         * 移除当前选中覆盖物
         * @returns {void}
         */
        removeOverlay() {
            this.mapEntity.removeOverlay(this.curClickOverLay)
            this.overlays = this.overlays.filter(item => {
                if (item.hashCode == this.curClickOverLay.hashCode) {
                    return false;
                }
                return true;
            });
        },
        /**
         * 清空所有面
         * @returns {void}
         */
        removeAllArea() {
            this.overlays = this.overlays.filter(item => {
                if (item instanceof BMapGL.Polygon) {
                    this.mapEntity.removeOverlay(item);
                    return false;
                }
                return true;
            });
        },
        /**
         * 清除所有线
         * @returns {void}
         */
        removeAllLine() {
            this.overlays = this.overlays.filter(item => {
                if (item instanceof BMapGL.Polyline) {
                    this.mapEntity.removeOverlay(item);
                    return false;
                }
                return true;
            });
        },
        /**
         * 清除所有点
         * @returns {void}
         */
        removeAllPoint() {
            this.overlays = this.overlays.filter(item => {
                if (item instanceof BMapGL.Marker) {
                    this.mapEntity.removeOverlay(item);
                    return false;
                }
                return true;
            });
        },
        // 清除所有覆盖物
        removeAllOverlay() {
            this.mapEntity.clearOverlays();
        },
        // 批量绑定事件
        bindEvent() {
            let clickEvts = ['click', 'dblclick', 'rightclick'];
            // 绑定事件
            for (let i = 0; i < clickEvts.length; i++) {
                const event = clickEvts[i];
                for (let j = 0; j < this.overlays.length; j++) {
                    const overlay = this.overlays[j];
                    overlay.addEventListener(event, e => {
                        console.log(e);
                        switch (event) {
                            case 'click':
                                this.curClickOverLay = e.target;
                                var res = overlay.toString() + '被单击!';
                                break;
                            case 'dbclick':
                                var res = overlay.toString() + '被双击!';
                                break;
                            case 'rightclick':
                                var res = overlay.toString() + '被右击!';
                                this.showMenu(e)
                                this.curClickOverLay = e.target;
                                break;
                        }
                        // alert(res);
                    });
                }
            }

        },
        bindOne(overlay) {
            let clickEvts = ['click', 'dblclick', 'rightclick'];
            for (let i = 0; i < clickEvts.length; i++) {
                const event = clickEvts[i];
                overlay.addEventListener(event, e => {
                    switch (event) {
                        case 'click':
                            this.curClickOverLay = e.target;
                            var res = overlay.toString() + '被单击!';
                            break;
                        case 'dbclick':
                            var res = overlay.toString() + '被双击!';
                            break;
                        case 'rightclick':
                            var res = overlay.toString() + '被右击!';
                            this.showMenu(e)
                            this.curClickOverLay = e.target;
                            break;
                    }
                });
            }
        },
        showMenu(event) {
            this.$refs.customMenu.style.display = 'block';
            this.$refs.customMenu.style.left = event.pixel.x + 'px';
            this.$refs.customMenu.style.top = event.pixel.y + 'px';
        },
        hideMenu() {
            this.$refs.customMenu.style.display = 'none';
        },
        /**
         * 销毁地图
         * @returns {void}
         */
        destroyMap() {
            if (this.mapEntity) {
                this.mapEntity.clearOverlays();
                this.mapEntity.destroy();
                this.overlays = [];
                this.mapEntity = null;
            }
        }
    },
    destroyed() {
        this.destroyMap();
    }
}
</script>

<style lang="scss" scope>
.map-box {
    width: 100%;
    height: calc(100vh - 50px);
}

#map {
    width: 100%;
    height: 100%;
}

.button-box {
    z-index: 1000;
    position: absolute;
    top: 10px;
    left: 10px;
}

#custom-menu {
    display: none;
    z-index: 1000;
    position: absolute;
    background-color: #f9f9f9;
    border: 1px solid #ccc;
    padding: 5px 0;
}

.menu-item {
    padding: 5px 20px;
    cursor: pointer;
}
</style>